package com.matrix.draft.sockettest.newprotocoltcp;

import com.matrix.draft.sockettest.newprotocoltcp.handler.NewProtocolDecoder;
import com.matrix.draft.sockettest.newprotocoltcp.handler.NewProtocolEncoder;
import com.matrix.draft.sockettest.newprotocoltcp.handler.ServerHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.logging.LoggingHandler;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class NewProtocolTcpServer {
    private String host = "127.0.0.1";
    private Integer port = 8080;
    public void run() {
        // Prepare two groups.
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        Channel serverChannel;
        try {
            // Run the server.
            serverChannel = new ServerBootstrap().group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG, 128)
                    // 系统的接收缓冲区(滑动窗口大小,系统会调制最优, 不用设置)
//                    .option(ChannelOption.SO_RCVBUF,5)
                    // Netty的接收缓冲区(ctx.alloc().buffer()产生的ByteBuf的默认大小)
//                    .childOption(ChannelOption.RCVBUF_ALLOCATOR,new AdaptiveRecvByteBufAllocator(16,16,16))
                    .childOption(ChannelOption.SO_KEEPALIVE, true) // TCP的2小时长连接监控机制
                    .childHandler(new ChannelInitializer<NioSocketChannel>() {
                        @Override
                        protected void initChannel(NioSocketChannel ch) throws Exception {
                            ChannelPipeline pipeline = ch.pipeline();
                            // Duplex
                            pipeline.addLast(new LoggingHandler());
                            // Out
                            pipeline.addLast(new NewProtocolEncoder());
                            // In
                            pipeline.addLast(new LengthFieldBasedFrameDecoder(2048,18,4,0,0));
                            pipeline.addLast(new NewProtocolDecoder());
                            pipeline.addLast(new ServerHandler());
                        }
                    })
                    .bind(host, port)
                    .addListener(f -> {
                        if (f.isSuccess()) {
                            log.info("The Generic Server is running...");
                        }
                    })
                    .sync().channel();
            // Close the channel.
            serverChannel.closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            // Finally,shutdown the two groups gracefully.
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

    public static void main(String[] args) {
        new NewProtocolTcpServer().run();
    }
}